package cn.com.idmy.auth.cookie;


import cn.com.idmy.base.util.Assert;
import lombok.Data;
import lombok.experimental.Accessors;
import org.dromara.hutool.core.text.StrUtil;

import java.time.Instant;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;

@Data
@Accessors(fluent = true)
public class Cookie {
    public static final String HEADER_NAME = "Set-Cookie";
    protected String name;
    protected String value;
    protected long maxAge = -1;
    protected String domain;
    protected String path;
    protected Boolean secure = false;
    protected Boolean httpOnly = false;
    protected String sameSite;

    /**
     * Set-Cookie: name=value; Max-Age=100000; Expires=Tue, 05-Oct-2021 20:28:17 GMT; Domain=localhost; Path=/; Secure; HttpOnly; SameSite=Lax
     */
    @Override
    public String toString() {
        if (path == null) {
            path = "/";
        }
        name = Assert.notBlank(name, "cookie name 不能为空");
        if (value != null && value.contains(";")) {
            throw new IllegalArgumentException("无效 cookie value：" + value);
        }

        StringBuilder sb = new StringBuilder();
        sb.append(name).append("=").append(value);

        if (maxAge >= 0) {
            sb.append("; Max-Age=").append(maxAge);
            String expires;
            if (maxAge == 0) {
                expires = Instant.EPOCH.atOffset(ZoneOffset.UTC).format(DateTimeFormatter.RFC_1123_DATE_TIME);
            } else {
                expires = OffsetDateTime.now().plusSeconds(maxAge).format(DateTimeFormatter.RFC_1123_DATE_TIME);
            }
            sb.append("; Expires=").append(expires);
        }
        if (StrUtil.isNotBlank(domain)) {
            sb.append("; Domain=").append(domain);
        }
        if (StrUtil.isNotBlank(path)) {
            sb.append("; Path=").append(path);
        }
        if (secure) {
            sb.append("; Secure");
        }
        if (httpOnly) {
            sb.append("; HttpOnly");
        }
        if (StrUtil.isNotBlank(sameSite)) {
            sb.append("; SameSite=").append(sameSite);
        }
        return sb.toString();
    }
}
